home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
422_02
/
dosutil
/
hexed.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-20
|
9KB
|
396 lines
/*
* Hexidecimal screen editor:
* NOTE: Must be compiled in SMALL model!
*
* Special Keys:
* PgDn = Page forward
* PgUp = Page backward
* CTRL-PgUp = Goto start of file
* CTRL-PgDn = Goto end of file
* Home = Goto start of line
* End = Goto end of line
* Ins = Insert a byte at cursor location
* Del = Delete a byte at cursor location
* F1 = Toggle between HEX/ASCII editing
* CTRL-Home = Redraw screen
* F10/Keypad '+' = Enter command
* F9/Keypad '-' = Re-execute last command
* Commands:
* G<xxxx> = Goto address xxxx
* Q = Quit editor
* QQ = Quit even if unsaved changes
* W[file] = Write file
* X[file] = Exit and write file
* ?xx ... = Search for HEX byte pattern
* /text... = Search for ASCII text
*
* Copyright 1983-1994 Dave Dunfield
* All rights reserved
*
* Permission granted for personal (non-commercial) use only.
*
* Compile command: cc hexed -fops
*/
#include <stdio.h>
#include <video.h>
#include <file.h>
#define ALLOCATION 60001
char cmdbuf[50], *cmdptr, searchbuf[50];
/* Declare data buffer in two chunks, to prevent a negative size,
which confuses MASM */
unsigned char data[ALLOCATION/2], data1[ALLOCATION/2];
/*
* Skip to the next non-blank character
*/
char skip()
{
while(*cmdptr == ' ')
++cmdptr;
return *cmdptr;
}
main(argc, argv)
unsigned argc;
char *argv[];
{
int cursor;
unsigned i, j, k, pos, size;
unsigned char c, chr, mode, modified;
HANDLE fh;
cursor = pos = mode = modified = 0;
if(argc<2)
abort("\nUse: hexed <file>\n\nCopyright 1983-1994 Dave Dunfield\nAll rights reserved.\n");
if(!(fh=open(argv[1], F_READ)))
abort("HEXED: Cannot open input file\n");
if((size = read(data, ALLOCATION, fh)) >= ALLOCATION)
abort("HEXED: File to large\n");
close(fh);
vopen();
draw: /* draw entire screen */
vgotoxy(0,0);
for(i=0; i<30; ++i) vputc('-');
V_ATTR = REVERSE;
putstr(" Hex-Ed Version 1.3 ");
V_ATTR = NORMAL;
for(i=0; i<30; ++i) vputc('-');
vgotoxy(0,2);
vprintf("File: %s",argv[1]);
vgotoxy(59,2);
vprintf("Size: %u, ($%04x)",size, size);
redraw: /* re-draw text area of screen */
for(i=0; i < 16; ++i) { /* for each line */
vgotoxy(0, i+4);
if(size <= (k=pos+(i*16)))
break;
vprintf("%04x ",k=pos+(i*16));
for(j = k; j < (k+16) ; ++j) {
if(j<size)
vprintf(" %02x", data[j]);
else {
vcleol();
break; } }
vgotoxy(63,i+4);
for(j = k; (j<(k+16)) && (j<size); ++j)
putprint(data[j]); }
vcleos();
prompt:
if(mode)
vgotoxy(63 + cursor%16, 4 + cursor/16);
else
vgotoxy(7+3*(cursor%16), 4+cursor/16);
switch(chr = vgetc()) {
case _KUA : /* backup a line (16 bytes) */
if((cursor = cursor - 16) < 0) {
cursor += 16;
case _KPU : /* backup a page (256 bytes) */
if(pos > 255) {
pos -= 256;
goto redraw; }
else if(pos) {
pos = 0;
goto redraw; } }
break;
case _KDA : /* advance a line (16 bytes) */
if((cursor + pos + 16) >= size)
break;
if(cursor <= (255-16)) {
cursor += 16;
break; }
case _KPD : /* advance a page (256 bytes) */
if((pos+256) < size)
pos += 256;
if((pos + cursor) > size)
cursor = size - pos - 1 ;
goto redraw;
case _KLA : /* backup one byte */
if(cursor)
--cursor;
else if(pos) {
--pos;
goto redraw; }
break;
case _KRA : /* advance one byte */
if(size <= (pos + ++cursor)) --cursor;
else if(255 < cursor) {
--cursor;
if(pos < (size - 255)) ++pos;
goto redraw; }
break;
case _CPD : /* goto end of file */
if(size > 255) {
cursor = 255;
pos = size - 256; }
else {
cursor = size-1;
pos = 0; }
goto redraw;
case _CPU : /* goto start of file */
cursor = pos = 0;
goto redraw;
case _KEN : /* advance to end of field */
cursor = (cursor & 0xff0) + 15;
if(size <= cursor+pos)
cursor = size - pos - 1;
break;
case _KHO : /* backup to beginning of field */
cursor = cursor & 0xff0;
break;
case _K1 : /* swap editing field */
mode = ~mode;
break;
case _CHO : /* re-draw the screen */
vclscr();
goto draw;
case _KDL: /* Delete a byte */
i = pos + cursor;
while(i < size)
data[i] = data[++i];
if((pos + cursor) >= --size) {
if(cursor)
--cursor;
else if(pos)
--pos; }
modified = -1;
goto redraw;
case _KIN: /* Insert a byte */
i = pos + cursor;
if(size < ALLOCATION) {
chr = data[i];
while(i < size) {
c = data[++i];
data[i] = chr;
chr = c; }
++size; }
modified = -1;
goto redraw;
case _K10 : /* execute line mode command */
case _KKP :
vgotoxy(0,22);
vcleos();
vputs("Command: ");
i = 0;
do {
if((chr = vgetc()) == _KBS) {
if (i) {
putstr("\010 \010");
--i; } }
else if(chr < 128)
vputc(cmdbuf[i++] = chr); }
while((chr != _KKP) && (chr != _K10));
cmdbuf[i] = 0;
case _K9 : /* repeat last command */
case _KKM :
vgotoxy(0, 22);
V_ATTR = REVERSE;
putstr(cmdbuf);
V_ATTR = NORMAL;
vcleos();
cmdptr = cmdbuf;
switch(chr = toupper(skip())) {
case 'G' : /* goto address */
++cmdptr;
skip();
i = 0;
if((i = gethex()) == -1)
break;
cursor = 0;
pos = (i<size) ? i : size;
goto redraw;
case '/' : /* Search for ASCII */
i = 0;
while(*++cmdptr)
searchbuf[i++] = *cmdptr;
if(!i)
break;;
goto do_search;
case '?' : /* search for HEX */
++cmdptr;
skip();
i = 0;
do
searchbuf[i++] = j = gethex();
while((j != -1) && skip());
if(j == -1)
break;
do_search: j = pos + cursor + 1;
while(!compare(searchbuf, data+j, i)) {
if(++j >= size) {
error("Not found");
break; } }
if(j < size) {
if((cursor = j - pos) & 0xff00) {
pos = j;
cursor = 0;
goto redraw; } }
break;
case 'X' : /* Exit and write file */
case 'W' : /* write file */
++cmdptr;
if(!skip())
cmdptr = argv[1];
if(fh=open(cmdptr, F_WRITE)) {
write(data, size, fh);
modified = 0;
close(fh); }
else {
error("Can't open output file");
break; }
if(chr != 'X')
break;
case 'Q' : /* quit (Exit) */
if(modified && (toupper(*(cmdptr+1)) != 'Q'))
error("Unsaved changes, 'qq' to quit anyway");
else {
vclscr();
exit(0); }
break;
case 0 : /* null command, do nothing */
break;
default:
error("Unknown command"); }
vgotoxy(0,22);
vcleol();
break;
default:
k = data[pos + cursor];
if(mode) {
data[pos+cursor] = k = chr;
chr = modified = -1; }
else {
if(ishex(chr = toupper(chr))) {
vputc(chr);
if(chr > '9') chr -= 7;
i = (chr-'0')*16;
vputc('-');
vputc('\b');
if(ishex(chr=toupper(vgetc()))) {
if(chr > '9') chr -= 7;
data[pos+cursor] = k =(chr-'0') + i;
chr = modified = -1; } } }
vgotoxy(7+3*(cursor%16), 4+cursor/16);
vprintf("%02x ",k);
vgotoxy(63 + cursor%16, 4 + cursor/16);
putprint(k);
if(chr == -1) {
if(size <= (pos + ++cursor)) --cursor;
else if(cursor > 255) {
if(pos < (size-256)) {
pos += 256;
cursor = 0; }
else
pos = size-(pos + cursor);
goto redraw; } } }
goto prompt;
}
/*
* Test for a valid hexidecimal digit
*/
ishex(chr)
char chr;
{
return ((chr >= '0') && (chr <= '9')) || ((chr >= 'A') && (chr <= 'F'));
}
/*
* Get a hex value from the input line
*/
gethex()
{
register unsigned i;
register char chr, flag;
flag = i = 0;
while(ishex(chr = toupper(*cmdptr))) {
++cmdptr;
flag = -1;
if(chr > '9')
chr -= 7;
i = (i*16) + (chr - '0'); }
if(!flag) {
error("Invalid HEX digit");
return -1; }
return i;
}
/*
* Dis